#include "SGD Wrappers/CSGD_TextureManager.h"
#include "CWorldManager.h"
#include <iostream>
#include <fstream>

CWorldManager::CWorldManager( void )
{

}

CWorldManager* CWorldManager::GetInstance( void )
{
	static CWorldManager instance;
	return &instance;
}

void CWorldManager::Start( void )
{
	//If anything needs to be initialized, do it here
}

void CWorldManager::Render( void )
{
	std::vector<CLayer*>::iterator itr;
	for ( itr = m_vTileLayers.begin(); itr < m_vTileLayers.end(); ++itr )
	{
		(*itr)->Render();
	}
}

void CWorldManager::ShutDown( void )
{
	for( unsigned int index = 0; index < m_vTileLayers.size(); index++ )
		delete m_vTileLayers[index];

	for( unsigned int index = 0; index < m_vEventLayers.size(); index++ )
		delete m_vEventLayers[index];
}

void CWorldManager::Update( float fElapsedTime )
{
	//If anything needs to be updated, do it here
}

bool CWorldManager::Load( char * szFilename )
{
	std::fstream file( szFilename, std::ios::in | std::ios::binary );
	
	if( file.is_open() )
	{
		int layerCount;

		vector<CLayer *> tempVectors;

		file.read( ( char* )&layerCount, sizeof( int ) );

		for( int index = 0; index < layerCount; index++ )
		{
			CLayer * temp = new CLayer;

			//Layer Name Lenght
			int strlen;
			file.read( ( char * )&strlen, sizeof( int ) );
			
			//Layer Name
			char tempChar[128] = { 0 };
			file.read( tempChar, sizeof( char ) );
			file.read( tempChar, ( sizeof( char ) * strlen ) );
			
			//Layer Type
			int layerType;
			file.read( ( char * )&layerType, sizeof( int ) );
			temp->SetType( layerType );
	
				//Layer ID
				int tempInt;

				file.read( ( char * )&tempInt, sizeof( int ) );
				temp->SetID( tempInt );
				
				//Layer Parent
				file.read( ( char * )&tempInt, sizeof( int ) );
				temp->SetParentID( tempInt );
				
				//Layer Rows
				file.read( ( char * )&tempInt, sizeof( int ) );
				temp->SetRows( tempInt );

				//Layer Columns
				file.read( ( char * )&tempInt, sizeof( int ) );
				temp->SetColumns( tempInt );

				//Tile Set Rows
				file.read( ( char * )&tempInt, sizeof( int ) );

				//Tile Set Columns
				file.read( ( char * )&tempInt, sizeof( int ) );

				//Tile Width 
				file.read( ( char * )&tempInt, sizeof( int ) );
				temp->SetTileWidth( tempInt );

				//Tile Height
				file.read( ( char * )&tempInt, sizeof( int ) );
				temp->SetTileHeight( tempInt );

				//Image String/ID
				file.read( ( char * )&strlen, sizeof( int ) );
				file.read( tempChar, sizeof( char ) );
				file.read( tempChar, ( sizeof( char ) * strlen ) );
				if( strcmp( tempChar, "null" ) != 0 )
					temp->SetImageID( CSGD_TextureManager::GetInstance()->LoadTexture( tempChar ) );
			
				//Tile Array
				temp->CreateTileArray( temp->GetRows(), temp->GetColumns() );

				for( int x = 0; x < temp->GetColumns(); x++ )
				{
					for( int y = 0; y < temp->GetRows(); y++ )
					{
						CTile tempTile;

						//Tile Array X
						int tileX;
						file.read( ( char * )&tileX, sizeof( int ) );

						//Tile Array Y
						int tileY;
						file.read( ( char * )&tileY, sizeof( int ) );

						//Rect X
						int selectedX;
						file.read( ( char * )&selectedX, sizeof( int ) );
			
						//Rect Y
						int selectedY;
						file.read( ( char * )&selectedY, sizeof( int ) );

						//Rect
						RECT tempRect;
						SetRect( &tempRect, selectedX * temp->GetTileWidth(), selectedY * temp->GetTileHeight(), 
							( selectedX * temp->GetTileWidth() ) + temp->GetTileWidth(), ( selectedY * temp->GetTileHeight() ) + temp->GetTileHeight() );

						tempTile.SetTileRect( tempRect );
	
						//Trigger
						char trigger[128] = { 0 };
						file.read( ( char * )&strlen, sizeof( int ) );
						file.read( trigger, sizeof( char ) );
						file.read( trigger, ( sizeof( char ) * strlen ) );
						if( strcmp( trigger, "null" ) != 0 )
							tempTile.SetTrigger( trigger );
						else
							tempTile.SetTrigger( "null" );

						//Collision
						bool tempBool;
						file.read( ( char * )&tempBool, sizeof( bool ) );
						tempTile.SetCollidable( tempBool );

						//Magnetism
						file.read( ( char * )&tempBool, sizeof( bool ) );
						tempTile.SetMagnetic( tempBool );

						//Gravity
						file.read( ( char * )&tempBool, sizeof( bool ) );
						tempTile.SetGravity( tempBool );
						
						//Event
						SEvent tempEvent;

						char eventChar[128] = { 0 };
						file.read( ( char * )&strlen, sizeof( int ) );
						file.read( eventChar, sizeof( char ) );
						file.read( eventChar, ( sizeof( char ) * strlen ) );
						if( strcmp( eventChar, "null" ) != 0 )
						{
							tempEvent.m_sEvent = eventChar;
							file.read( ( char * )&tempBool, sizeof( bool ) );
							tempEvent.m_bHasGravity = tempBool;

							file.read( ( char * )&tempInt, sizeof( int ) );
							tempEvent.m_nWidth = tempInt;

							file.read( ( char * )&tempInt, sizeof( int ) );
							tempEvent.m_nHeight = tempInt;

							file.read( ( char * )&tempInt, sizeof( int ) );
							tempEvent.m_nPolarity = tempInt;

							tempTile.SetEvent( tempEvent );
						}
						else
						{
							tempEvent.m_sEvent = "null";
							tempTile.SetEvent( tempEvent );
						}


						temp->SetTile( tempTile, x, y );
					}
				}

				//Put in proper vector
				if( temp->GetType() == 0 )
					m_vTileLayers.push_back( temp );
				else if( temp->GetType() == 1 )
					m_vEventLayers.push_back( temp );
				else
					tempVectors.push_back( temp );
		}

		while( tempVectors.size() > 0 )
		{

			CLayer * tempLayer = tempVectors.front();

			CLayer * parentLayer;

			tempVectors.pop_back();

			int Parent = tempLayer->GetParentID();

			std::vector<CLayer*>::iterator itr;
			for ( itr = m_vTileLayers.begin(); itr < m_vTileLayers.end(); ++itr )
			{
				if( (*itr)->GetID() == Parent )
				{
					parentLayer = (*itr);
					break;
				}
			}

			for( int x = 0; x < tempLayer->GetColumns(); x++ )
			{
				for( int y = 0; y < tempLayer->GetRows(); y++ )
				{
					if( tempLayer->GetType() == 2 )
					{
						CTile tempTile = parentLayer->GetTile( x, y );

						tempTile.SetCollidable( tempLayer->GetTile(x,y).GetCollidable() );

						parentLayer->SetTile( tempTile, x, y );
					}
					else if( tempLayer->GetType() == 3 )
					{
						CTile tempTile = parentLayer->GetTile( x, y );

						tempTile.SetMagnetic( tempLayer->GetTile(x,y).GetMagnetic() );

						parentLayer->SetTile( tempTile, x, y );
					}
					else if( tempLayer->GetType() == 4 )
					{
						CTile tempTile = parentLayer->GetTile( x, y );

						tempTile.SetTrigger( tempLayer->GetTile(x,y).GetTrigger() );

						parentLayer->SetTile( tempTile, x, y );
					}

				}
			}
		}

		file.close(); 

		CallEvents();
	}
	else
	{
		file.close();
		return false;
	}

	return true;
}

void CWorldManager::CallEvents( void )
{

	std::vector<CLayer*>::iterator itr;
	for ( itr = m_vEventLayers.begin(); itr < m_vEventLayers.end(); ++itr )
	{
		//Loop through tiles and use switch to do events
	}

}